#ifndef DROP_CUTTER_HPP
#define DROP_CUTTER_HPP
#include <vector>
#include <map>



#include "position_solutions.h"
#include "point.hpp"

//#include "octree/octree.h"
#include "bbox.hpp"
#include "boxtests.hpp"

#include "notifiers.hpp"


using std::vector;
using std::map;


class drop_cylinder_cutter_3d;

class Octree{
public:
	Octree(int c){
		cells=c;
	}
	int size(){
		return cells;
	}
	long hash(int x, int y, int z){
		return cells*cells*x+cells*y+z;
	}
	triar& operator()(int x, int y, int z){
		return tr[hash(x,y,z)];
	}
 int cells;
 map<long,triar> tr;
};


class tracing_note
{
public:  
  tracing_note()
    {}
  virtual ~tracing_note()
  {
  }
  
 virtual void tic(const char* ,int pc, drop_cylinder_cutter_3d &cutter)
  {
  }
};


struct spacetree
{
  spacetree();
  spacetree(const triar &model,int cells);
  void sort_traverse(const bbox& b,const triang &tri);

  void cyltraverse(const point &o, const point &n,
			      double d,triar *tris);
  

    void cyltraverse(const matr &frame,double d,triar *tris);
    
  void  cyltraverse(const point &o, const point &n,double d, const bbox &b,
		    triar *tris);

  double xmin(){return box.x0;}
  double xmax(){return box.x0+box.ax;}
  double ymin(){return box.y0;}
  double ymax(){return box.y0+box.ay;}
  
  
  
  Octree tree;
  bbox box;
};

  
  
class drop_cylinder_cutter_3d
{
public:
  drop_cylinder_cutter_3d()
  {
  }
  
    
  drop_cylinder_cutter_3d(const triar &model,int cells);
  point gen_pathpoint(double tool_diameter,double safe_z,
		      const point &o,const point &d);

  point gen_5axis_pathpoint(double tool_diameter,double safe_z,
			    const point &o, const point &d=point(0,0,1));
  
  
  point spec_tri_normal(double x,double y, double *z=NULL);
  
  vector<point> gen_toolpath(double tool_diameter,
			     double dx,double dy,double safe_z,
			     tracing_note *note=NULL);


  vector<point> toolpath;
  spacetree tree;
};

  
  
class drop_cylinder_cutter_2d
{
public:
  
  drop_cylinder_cutter_2d()
  {
    cx=cy=xmin=xmax=ymin=ymax=NA;    
  }
  void setmodel(const triar &_model);
  
  vector<point>  gen_toolpath(double tool_diameter,double dx,double dy,double safe_z);
  
  
  
private:

  double
    xmin, xmax,
    ymin, ymax,
    c0x,c0y,
    c1x,c1y,
    cx,cy;
      
  
  struct cluster;
  
  struct cluster
  {
    double
      xmin, xmax,
      ymin, ymax;
    triar tris;
    vector<cluster> clus;
  };

  
  void down_sort(double dx,double dy, cluster &parent);
  
 
  bool drop_cutter(const cluster &clus,
		   double x,double y,double r,double safe_z,double *z);
  
  
 cluster clus;   
 
 
  vector<point> toolpath;
   
};


void intersect_line(point p1, point p2,
		    double xc, double yc, double r,
		    vector<double> &z_vals);
int solve_sq(double a, double b, double c, double &x1, double &x2);
bool iz_right(point p1, point p2, double x, double y);
bool t_max(const vector<double> &v,double *r);
bool cross_test2d(point a1, point a2, point b1, point b2);
bool in_tri(point p1, point p2, point p3,
		   double x, double y);
double max(const vector<double> &v);
bool intersect_triangle(const triang &tr, double xc, double yc, double r,double *z);
bool intersect_triangle(const triang &tr, const  matr &ori, double r,double *z);

#endif
  

       
       
